(function (angular) {
    'use strict';
    var commonModule = angular.module("fs.common");
    commonModule.factory('arithService', arithService);
    arithService.$inject = [];
    function arithService() {
		/*
		 * add computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
        function add() {
            var data = "0";
            if (arguments.length > 0) {
                if (typeof (arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
                var v = new Big(arguments[0]);
                for (var i = 1; i < arguments.length; i++) {
                    if (typeof (arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
                    v = v.plus(new Big(arguments[i]));
                }
                data = v.toString();
            }
            return (data);
        }

		/*
		 * subtration computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
        function sub() {
            var data = "0";
            if (arguments.length > 0) {
                if (typeof (arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
                var v = new Big(arguments[0]);
                for (var i = 1; i < arguments.length; i++) {
                    if (typeof (arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
                    v = v.minus(new Big(arguments[i]));
                }
                data = v.toString();
            }
            return (data);
        }

		/*
		 * multiplication computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
        function mul() {
            var data = "0";
            if (arguments.length > 0) {
                if (typeof (arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
                var v = new Big(arguments[0]);
                for (var i = 1; i < arguments.length; i++) {
                    if (typeof (arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
                    v = v.times(new Big(arguments[i]));
                }
                data = v.toString();
            }
            return (data);
        }

		/*
		 * dividing computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
        function div() {
            var data = "0";
            if (arguments.length > 0) {
                if (typeof (arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
                var v = new Big(arguments[0]);
                for (var i = 1; i < arguments.length; i++) {
                    if (typeof (arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
                    v = v.div(new Big(arguments[i]));
                }
                data = v.toString();
            }
            return (data);
        }

		/*
		 * mathematical computation
		 * @param num1 support numbers
		 * @param num2 support numbers
		 * @param type the operator: '+', '-', '*', '/'
		 * @return number
		 */
        function calc(num1, num2, type) {
            if (type == '+') return (this.add(num1, num2));
            if (type == '-') return (this.sub(num1, num2));
            if (type == '*') return (this.mul(num1, num2));
            if (type == '/') return (this.div(num1, num2));
        }

		/**
		 * quickly compute the average of the number/string array and the return value is not accurate
		 * @param support for multiple numbers or multiple objects
		 * @return string of average
		 */
        function quickAverage() {
            if (arguments.length == 0) return NaN;
            var v = new Big(arguments[0]);
            for (var i = 1; i < arguments.length; i++) {
                v = v.plus(arguments[i]);
            }
            return v.div(arguments.length).toString();
        }

		/**
		 * Returns the maximum of this array of number
		 * @param support for multiple numbers
		 * @return maximum
		 */
        function max() {
            if (arguments.length == 0) return NaN;
            var max = new Big(Number.MIN_VALUE);
            for (var i = 0; i < arguments.length; i++) {
                if (max.lt(arguments[i])) {
                    max = new Big(arguments[i]);
                }
            }
            return max.toString();
        }

		/**
		 * Returns the minimum of this array of number
		 * @param support for multiple numbers
		 * @return minimum
		 */
        function min() {
            if (arguments.length == 0) return NaN;
            var min = new Big(Number.MAX_VALUE);
            for (var i = 0; i < arguments.length; i++) {
                if (min.gt(arguments[i])) {
                    min = new Big(arguments[i]);
                }
            }
            return min.toString();
        }

		/**
		 * Returns true only if num1 greater than num2
		 * @param num1, num2
		 * @return true only if num1 greater than num2
		 */
        function gt(num1, num2) {
            if (arguments.length != 2) throw new Error('incorrect arguments number!');
            var l = new Big(num1);
            var r = new Big(num2);
            return l.gt(r);
        }

		/**
		 * Returns true if num1 greater than num2 or num1 equals to num2 
		 * @param num1, num2
		 * @return true if num1 greater than num2 or num1 equals to num2
		 */
        function gte(num1, num2) {
            if (arguments.length != 2) throw new Error('incorrect arguments number!');
            var l = new Big(num1);
            var r = new Big(num2);
            return l.gte(r);
        }

		/**
		 * Returns true only if num1 equal to num2
		 * @param num1, num2
		 * @return true only if num1 equal to num2
		 */
        function eq(num1, num2) {
            if (arguments.length != 2) throw new Error('incorrect arguments number!');
            var l = new Big(num1);
            var r = new Big(num2);
            return l.eq(r);
        }

		/**
		 * Returns true only if num1 less than num2
		 * @param num1, num2
		 * @return true only if num1 less than num2
		 */
        function lt(num1, num2) {
            if (arguments.length != 2) throw new Error('incorrect arguments number!');
            var l = new Big(num1);
            var r = new Big(num2);
            return l.lt(r);
        }

		/**
		 * Returns true if num1 less than num2 or num1 equals to num2
		 * @param num1, num2
		 * @return true if num1 less than num2 or num1 equals to num2
		 */
        function lte(num1, num2) {
            if (arguments.length != 2) throw new Error('incorrect arguments number!');
            var l = new Big(num1);
            var r = new Big(num2);
            return l.lte(r);
        }

        return {
            add: add,
            sub: sub,
            mul: mul,
            div: div,
            calc: calc,
            quickAverage: quickAverage,
            max: max,
            min: min,
            gt: gt,
            gte: gte,
            eq: eq,
            lt: lt,
            lte: lte
        };
    }
})(angular);